/* Include files. */
extern "C" { 
	#include "standard.h"
	#include "debug.h"
}

#include "ubusmgr.h"
#include "event.h"
#include "subsystemcore.h"
#include "object.h"

/* Local function declarations. */

/* Macro API definitions. */

/* Global variable declarations. */

/* Type definitions. */

/* Local function definitions. */

static map<string , ubusEvent *> event_map;


#ifdef U_LOOP
static struct ubus_context *ubus = NULL;
static ubusEvent* findEvent(string key) 
{
	map<string, ubusEvent *>::iterator ite = event_map.find(key);  
	if(ite == event_map.end()){
		ERROR("findEvent %s failed!\n", key.c_str());
		ASSERT(0);
		return NULL;
	}
	else{  
		return ite->second;  
	}  
}

static void unRegEvent(struct ubus_context *ubus, const char *event)
{
	ubusEvent *ubusev = findEvent(event);
	event_map.erase(event);
	ubus_unregister_event_handler(ubus, &ubusev->_listener);  	
	delete ubusev;
	return;
}

void eventCallback( struct ubus_context *ctx, struct ubus_event_handler *ev,  
            	const char *event, struct blob_attr *msg)  
{  
    if (msg) {
		char *json_str = blobmsg_format_json(msg, true);  
		DEBUG("ubus event %s %s\n", event, json_str);
		ubusEvent* ubusev = findEvent(string(event));
		subSystem *sub = ubusev->_sub;
		if (sub != NULL) {
			sendSubSystem(ubusev->_L, sub->_name.c_str(), sub->_name.c_str(), 
				"response", json_str, ubusev->_session);
		}
		else {
			WARN("%s already free!\n", sub->_name.c_str());
			#ifdef U_LOOP
			if (ubus)
				unRegEvent(ubus, event);
			#endif
		}
		free(json_str); 
	}
	else {
		ERROR("msg is null\n");
		ASSERT(0);
	}
} 

static void regEvent(struct ubus_context *ubus, const char *event, u32 session, lua_State *L)  
{  
	ubusEvent* ubusev = new ubusEvent(event, session, L);
	event_map[event] = ubusev;
	ubusev->_listener.cb = eventCallback; 
    int ret = ubus_register_event_handler(ubus, &ubusev->_listener, ubusev->_name.c_str());  
    if (ret) {  
        ERROR("regEvents %s failed.\n", event);  
        return;  
    }  
	return;
} 
#endif

int luaConnectUbus(lua_State *L)
{
	#ifdef U_LOOP
	if (!(ubus = ubus_connect(NULL))) {
		/*TODO: ��ʱδ��������*/
		ERROR("unable to connect to ubus: %s\n", strerror(errno));
		ASSERT(0);
		return 0;
	}
	ubus_add_uloop(ubus);
	#endif
	DEBUG("connect ubusd success!\n");
	return 0;
}

int luaregEvent(lua_State *L) 
{
	#ifdef U_LOOP
	const char* event = lua_tostring(L, -2);
	u32 session = lua_tointeger(L, -1);
	if (ubus)
		regEvent(ubus, event, session, L);
	#endif
	lua_pushboolean(L, true);
	return 1;
}

int luaunRegEvent(lua_State *L) 
{
	#ifdef U_LOOP
	const char* event = lua_tostring(L, -1);
	if (ubus)
		unRegEvent(ubus, event);
	#endif
	lua_pushboolean(L, true);
	return 1;
}

